<?php
// 内置HTTP服务器核心类
class HttpServer
{
    private $address;
    private $port = 0;
    private $rootPath;
    private $socket;

    public function __construct($address = '127.0.0.1', $port = 8000, $rootPath = __DIR__)
    {
        $this->address = $address;
        $this->port = $port;
        $this->rootPath = realpath($rootPath);
    }

    // 启动HTTP服务器
    public function start()
    {

        // 创建TCP套接字
        $this->socket = stream_socket_server(
            "tcp://{$this->address}:{$this->port}",
            $errno,
            $errstr
        );

        if (!$this->socket) {
            die("无法启动服务器: $errstr ($errno)");
        }

        // var_dump($this->socket);
        echo "服务器运行在 http://{$this->address}:{$this->port}\n";
        echo "根目录: {$this->rootPath}\n";
        echo "按Ctrl+C停止服务器\n";

        // 主服务循环
        while ($connection = stream_socket_accept($this->socket, -1)) {
            $this->handleConnection($connection);
            fclose($connection);
        }
    }

    // 处理客户端连接
    private function handleConnection($connection)
    {
        // 读取请求头
        $request = fread($connection, 8192);

        // printf($request . "\r\n");
        // return;
        // 解析HTTP请求
        $requestData = $this->parseRequest($request);

        // return;
        // 调用框架入口
        $response = $this->dispatchToFramework($requestData);

        // 发送HTTP响应
        fwrite($connection, $response);
    }

    // 解析HTTP请求
    private function parseRequest($request)
    {
        $lines = explode("\r\n", $request);
        $requestData = [
            'method' => '',
            'uri' => '',
            'headers' => [],
            'get' => [],
            'post' => [],
            'files' => [],
            'server' => [],
            'cookies' => []
        ];
        // var_dump($lines);
        // 解析请求行
        $firstLine = array_shift($lines);

        if (preg_match('/^(\w+)\s+([^\s]+)\s+HTTP\/(\d\.\d)/', $firstLine, $matches)) {
            // var_dump($matches);
            $requestData['method'] = $matches[1];
            $requestData['uri'] = $matches[2];
        }
        // return;

        // 解析请求头
        $parsingHeaders = true;
        $bodyLines = [];
        $contentLength = 0;

        foreach ($lines as $line) {
            if (empty($line) && $parsingHeaders) {
                $parsingHeaders = false;
                continue;
            }

            if ($parsingHeaders) {
                if (strpos($line, ': ') !== false) {
                    list($key, $value) = explode(': ', $line, 2);
                    $key = strtolower(str_replace('-', '_', $key));

                    // 特殊处理Content_Type
                    if ($key == 'content_type') {
                        if (strpos($value, 'multipart/form-data') !== false) {
                            $requestData['content_type'] = $value;
                        } elseif (strpos($value, 'application/x-www-form-urlencoded') !== false) {
                            $requestData['content_type'] = $value;
                        }
                    }

                    // 存储内容长度
                    if ($key == 'content_length') {
                        $contentLength = (int) $value;
                    }

                    $requestData['headers'][$key] = $value;
                }
            } else {
                $bodyLines[] = $line;
            }
        }

        // 解析查询参数
        $parts = parse_url($requestData['uri']);
        if (isset($parts['query'])) {
            parse_str($parts['query'], $requestData['get']);
        }

        // var_dump($requestData);
        // return;
        // 解析请求体
        $body = implode("\r\n", $bodyLines);
        if ($contentLength > 0 && strlen($body) >= $contentLength) {
            if (isset($requestData['content_type']) && strpos($requestData['content_type'], 'application/x-www-form-urlencoded') !== false) {
                parse_str($body, $requestData['post']);
            } elseif (isset($requestData['content_type']) && strpos($requestData['content_type'], 'multipart/form-data') !== false) {
                $this->parseMultipart($body, $requestData);
            }
        }
        // var_dump($body);
        // var_dump($bodyLines);
        return $requestData;
    }

    // 解析multipart表单数据
    private function parseMultipart($body, &$requestData)
    {
        $boundary = '--' . substr(
            $requestData['content_type'],
            strpos($requestData['content_type'], 'boundary=') + 9
        );


        $parts = explode($boundary, $body);
        // echo "parts:\r\n";
        // var_dump($parts);
        // return;
        foreach ($parts as $part) {
            if (trim($part) == '' || trim($part) == '--')
                continue;

            list($headers, $value) = explode("\r\n\r\n", $part, 2);
            $headers = explode("\r\n", trim($headers));

            // echo "headers:\r\n";
            // var_dump($headers);
            // var_dump($value);
            // return;
            $fieldName = '';
            $fileName = '';

            foreach ($headers as $header) {
                if (strpos($header, 'Content-Disposition:') === 0) {
                    if (preg_match('/name="([^"]+)"/', $header, $matches)) {
                        $fieldName = $matches[1];
                    }

                    if (preg_match('/filename="([^"]+)"/', $header, $matches)) {
                        $fileName = $matches[1];
                    }
                }
            }

            if ($fieldName) {
                if ($fileName) {
                    // 文件上传处理
                    $requestData['files'][$fieldName] = [
                        'name' => $fileName,
                        'type' => '',
                        'tmp_name' => '',
                        'error' => 0,
                        'size' => strlen($value),
                        'content' => $value
                    ];
                } else {
                    // 普通字段
                    $requestData['post'][$fieldName] = trim($value);
                }
            }
        }
    }

    // 将请求分派给ThinkPHP框架
    private function dispatchToFramework($requestData)
    {
        // 设置超全局变量
        $_SERVER = array_merge($_SERVER, [
            'REQUEST_METHOD' => $requestData['method'],
            'REQUEST_URI' => $requestData['uri'],
            'QUERY_STRING' => isset($requestData['get']) ? http_build_query($requestData['get']) : '',
            'CONTENT_TYPE' => $requestData['headers']['content_type'] ?? '',
            'CONTENT_LENGTH' => strlen(json_encode($requestData['post'] ?? ''))
        ]);

        $_GET = $requestData['get'];
        $_POST = $requestData['post'];
        $_FILES = $requestData['files'];

        // 捕获框架输出
        ob_start();

        // 调用框架入口文件
        require $this->rootPath . '/index.php';

        $responseBody = ob_get_clean();

        // var_dump($responseBody);
        // 构建HTTP响应
        return 
            // "HTTP/1.1 200 OK\r\n"
            // // . "Content-Type: text/html\r\n"
            // . "Content-Type: application/json; charset=utf-8\r\n"
            // . "Content-Length: " . strlen($responseBody) . "\r\n"
            // . "Connection: keep-alive\r\n\r\n"
            // . $responseBody;
            $responseBody;
    }
}

// 使用示例
$publicDir = __DIR__ . '/../public';  // 指向ThinkPHP框架的public目录
$server = new HttpServer('0.0.0.0', 8000, $publicDir);
$server->start();
?>